/****************************************************************************
 *  _____       ______  _____
 * |_   _|     |  ____|/ ____|
 *   | |  _ __ | |__  | (___    Institute of Embedded Systems
 *   | | | '_ \|  __|  \___ \   Zürcher Hochschule für Angewandte
 *  _| |_| | | | |____ ____) |  Wissenschaften
 * |_____|_| |_|______|_____/   8401 Winterthur, Switzerland
 *
 ****************************************************************************
 *
 * @version $Rev: 204 $
 * @author  $Author: bacr $
 * @date    $Date: 2013-12-20 16:54:25 +0100 (ven., 20 déc. 2013) $
 *
 ***************************************************************************/

#ifndef __PTP2_PACKET_H__
#define __PTP2_PACKET_H__

typedef struct ptp2_header_t ptp2_header_t;
typedef struct ptp2_packet_t ptp2_packet_t;

#include "hcpp/ptp2_types.h"

#define PTP2_PACKET(obj) ((ptp2_packet_t *) obj)

/* length on the wire! */
#define PTP2_PACKET_LEN                                 34

#define PTP2_PACKET_OFFSET_MSG_TYPE                     0
#define PTP2_PACKET_OFFSET_VERSION                      1
#define PTP2_PACKET_OFFSET_MSG_LEN                      2
#define PTP2_PACKET_OFFSET_DOMAIN_NUMBER                4
#define PTP2_PACKET_OFFSET_FLAGS                        6
#define PTP2_PACKET_OFFSET_CORRECTION                   8
#define PTP2_PACKET_OFFSET_SRC_PORT                     20
#define PTP2_PACKET_OFFSET_SEQ_ID                       30
#define PTP2_PACKET_OFFSET_CONTROL                      32
#define PTP2_PACKET_OFFSET_LOG_MSG_INTERVAL             33

#define PTP2_FLAG_LEAP61                                0x0001
#define PTP2_FLAG_LEAP59                                0x0002
#define PTP2_FLAG_CURRENT_UTC_OFFSET_VALID              0x0004
#define PTP2_FLAG_PTP_TIMESCALE                         0x0008
#define PTP2_FLAG_TIME_TRACEABLE                        0x0010
#define PTP2_FLAG_FREQUENCY_TRACEABLE                   0x0020
#define PTP2_FLAG_ALTERNATE_MASTER                      0x0100
#define PTP2_FLAG_TWO_STEP                              0x0200
#define PTP2_FLAG_UNICAST                               0x0400

#define PTP2_MESSAGE_TYPE_SYNC                          0x0
#define PTP2_MESSAGE_TYPE_DELAY_REQ                     0x1
#define PTP2_MESSAGE_TYPE_PDELAY_REQ                    0x2
#define PTP2_MESSAGE_TYPE_PDELAY_RESP                   0x3
#define PTP2_MESSAGE_TYPE_FOLLOW_UP                     0x8
#define PTP2_MESSAGE_TYPE_DELAY_RESP                    0x9
#define PTP2_MESSAGE_TYPE_PDELAY_RESP_FOLLOW_UP         0xa
#define PTP2_MESSAGE_TYPE_ANNOUNCE                      0xb
#define PTP2_MESSAGE_TYPE_SIGNALING                     0xc
#define PTP2_MESSAGE_TYPE_MANAGEMENT                    0xd

#define PTP2_PACKET_PORT_IDENTITY_LEN                   10
#define PTP2_PACKET_CLOCK_IDENTITY_LEN                  8
#define PTP2_PACKET_PORT_NUMBER_LEN                     2

#define PTP2_CONTROL_SYNC                               0x00
#define PTP2_CONTROL_DELAY_REQ                          0x01
#define PTP2_CONTROL_FOLLOW_UP                          0x02
#define PTP2_CONTROL_DELAY_RESP                         0x03
#define PTP2_CONTROL_MANAGEMENT                         0x04
#define PTP2_CONTROL_OTHERS                             0x05

#define PTP2_LOG_MSG_INTERVAL_SIGNALING                 0x7F

/* network byte order */
#define PTP2_HEADER                                 \
    union {                                         \
        uint8_t             msg_raw;                \
        struct {                                    \
            uint8_t         msg_type  : 4;          \
            uint8_t         transport : 4;          \
        };                                          \
    };                                              \
    uint8_t                 version;                \
    uint16_t                msg_len;                \
    uint8_t                 domain_number;          \
    uint16_t                flags;                  \
    ptp2_correction_t       correction;             \
    ptp2_port_identity_t    src_port_identity;      \
    uint16_t                seq_id;                 \
    uint8_t                 control;                \
    uint8_t                 log_msg_interval;

/**
 * @struct ptp2_header_t
 * @brief  PTP2 header
 * @see    ptp2_header_t
 *
 */
struct ptp2_header_t {
    PTP2_HEADER
};

/**
 * @struct ptp2_packet_t
 * @brief  PTP2 packet
 * @see    ptp2_packet_t
 *
 * @var    ptp2_packet_t::ether
 * @brief  Ethernet header
 *
 * @var    ptp2_packet_t::ip
 * @brief  IP header
 *
 * @var    ptp_packet_t::udp
 * @brief  UDP header
 */
struct ptp2_packet_t {
    object_t            obj;
    info_header_t       info;
    ethernet_header_t   ether;      /**< @brief Ethernet header */
    ip_header_t         ip;         /**< @brief IP Header */
    udp_header_t        udp;        /**< @brief UDP Header */
    PTP2_HEADER
};

uint32_t    ptp2_packet_encode(ptp2_packet_t *this, raw_packet_t *raw_packet, uint32_t ptp2_offset);
void        ptp2_packet_decode(ptp2_packet_t *this, raw_packet_t *raw_packet, uint32_t ptp2_offset);

#endif

